import { Controller } from 'egg';
import { Result } from '../util/result';
import MsgEnum from '../util/msgEnum';
import xlsx from 'node-xlsx';
import { get, isExistObject } from '../util/ossFile';
import RoleEnum from '../util/roleEnum';
import { SATISFY_MAX_SIZE, SATISFY_SUFFIX } from '../../constants/user-role';
import FileUtil from './../util/file';

const toArray = require('stream-to-array');
const sendToWormhole = require('stream-wormhole');

const isValidateSuffix = (filename: string) => {
  const filenameSplitedArr = filename.split('.');
  const suffix = filenameSplitedArr[filenameSplitedArr.length - 1];
  const lowerSuffix = suffix.toLowerCase();

  return SATISFY_SUFFIX.includes(`.${lowerSuffix}`);
};

export default class ProductController extends Controller {
  public async deleteProduct() {
    const { ctx } = this;
    const { id } = ctx.request.body;
    const result = await this.ctx.service.product.deleteProducts(id);
    if (result.mainData) {
      ctx.body = result;
    } else {
      ctx.status = 400;
      ctx.body = result;
    }
  }

  public async hasFile() {
    const { ctx } = this;
    const { id } = ctx.request.body;
    const res = await isExistObject(RoleEnum.PRODUCT, Number(id), '.pdf');
    if (res?.exist) {
      ctx.body = new Result(res, res.msg);
    } else {
      ctx.status = 400;
      ctx.body = new Result(res, res.msg);

    }
  }

  public async getProductFile() {
    const { ctx } = this;

    const { id } = ctx.query;
    const result = await get(RoleEnum.PRODUCT, Number(id), '.pdf');
    if (result.error) {
      ctx.status = 400;
      ctx.body = result;
    } else {
      this.ctx.attachment(result.file_name);
      this.ctx.set('Content-Type', 'application/octet-stream');
      ctx.body = result.result.stream;
    }

  }

  public async createProduct() {
    const { ctx } = this;

    ctx.validate({
      productNo: 'string',
      productId: { required: false, type: 'string' },
      name: 'string',
      registrationStatus: 'string',
      model: 'string',
      application_area: 'string',
      organization: { required: false, type: 'array' },
      address: { required: false, type: 'string' },
      patent: { required: false, type: 'string' },
      contactPerson: { required: false, type: 'string' },
      contactEmail: { required: false, type: 'string' },
      contactTel: { required: false, type: 'string' },
      description: 'string',
      updateTime: 'string',
      filler: 'string',
      company: 'string',
      pictureUrls: { required: false, type: 'array' },
    }, ctx.request.body);
    const {
      productNo,
      productId,
      name,
      registrationStatus,
      model,
      application_area,
      organization,
      address,
      patent,
      contactPerson,
      contactEmail,
      contactTel,
      description,
      updateTime,
      filler,
      company,
      pictureUrls,
    } = ctx.request.body;

    const result = await this.ctx.service.product.createProduct(
      productNo,
      productId,
      name,
      registrationStatus,
      model,
      application_area,
      organization,
      address,
      patent,
      contactPerson,
      contactEmail,
      contactTel,
      description,
      updateTime,
      filler,
      company,
      pictureUrls
    );

    if (!result) {
      ctx.status = 400;
      ctx.body = new Result({ result }, '添加失败');
      return;
    }
    ctx.body = new Result({ result }, '添加成功');

    // console.log(formData);

    // await ctx.getFileStream().then(async r => {
    //   console.log(r);
    //   const result = await this.ctx.service.product.createAll(r.fields);
    //   if (result.mainData) {
    //     ctx.body = result;
    //   } else {
    //     ctx.status = 400;
    //     ctx.body = result;
    //   }
    // });
  }

  public async getProductMaps() {
    const { ctx } = this;
    const data = await this.ctx.service.product.getProductMaps();
    if (data) {
      ctx.body = new Result(data, MsgEnum.GET_FINANCIAL_LIST_SUCCESS);

    } else {
      ctx.status = 400;
      ctx.body = new Result(data, MsgEnum.GET_FINANCIAL_LIST_SUCCESS);

    }
  }

  public async getAllPlace() {
    const { ctx } = this;
    const data = await this.ctx.service.product.getAllPlace();
    if (data) {
      ctx.body = new Result(data, MsgEnum.GET_FINANCIAL_LIST_SUCCESS);

    } else {
      ctx.status = 400;
      ctx.body = new Result(data, MsgEnum.GET_FINANCIAL_LIST_SUCCESS);

    }
  }


  public async getStatus() {
    const { ctx } = this;
    const data = await this.ctx.service.product.getStatus();
    if (data) {
      ctx.body = new Result(data, MsgEnum.GET_FINANCIAL_LIST_SUCCESS);

    } else {
      ctx.status = 400;
      ctx.body = new Result(data, MsgEnum.GET_FINANCIAL_LIST_SUCCESS);

    }
  }

  public async getFile() {
    // 同步
    const { ctx } = this;
    const stream = await ctx.getFileStream();
    const newBuffer = await toArray(stream).then(function (parts) {
      const buffers = [];
      for (let i = 0, l = parts.length; i < l; ++i) {
        const part = parts[i];
        buffers.push((part instanceof Buffer) ? part as never : new Buffer(part) as never);
      }
      return Buffer.concat(buffers);
    });
    const parse = xlsx.parse(
      newBuffer,
      { bookType: 'xlsx', bookSST: false, type: 'buffer' }
    );
    const data = parse[0].data.slice(1);
    const result = await this.ctx.service.product.createProducts(data, parse[0].data[0], stream.fields.username);
    if (result.mainData && result.mainData.upload) {
      ctx.body = result;
    } else {
      ctx.status = 400;
      ctx.body = result;
    }
    await sendToWormhole(stream, true)
      .then(() => console.log('done'))
      .catch(err => console.error(err));
  }

  public async testProductExist() {
    const { ctx } = this;
    const { name, model, unit } = ctx.request.body;
    const result = await this.ctx.service.product.testProductExist(name, model, unit);
    if (result.mainData) {
      ctx.body = result;

    } else {
      ctx.status = 406;
      ctx.body = result;
    }
  }

  public async uploadProduct() {
    const { ctx } = this;
    await ctx.getFileStream().then(async r => {
      const result = await this.ctx.service.product.uploadAll(
        r.fields.id,
        r.fields,
        r
      );
      if (result.mainData) {
        ctx.body = result;

      } else {
        ctx.status = 400;
        ctx.body = result;
      }
    });
  }

  public async getList() {
    const { ctx, app } = this;

    const errors = app.validator.validate(
      {
        page: { type: 'int', convertType: 'int' },
      },
      ctx.query
    );
    if (errors) {
      ctx.status = 401;
      ctx.body = new Result(errors, MsgEnum.PARAMETER_VERIFICATION_ERROR);
    } else {
      const { page, name, fk_applicationArea, date, keyword } = ctx.query;
      const result = await this.ctx.service.product.getProjectList(
        Number(page),
        name,
        fk_applicationArea,
        date,
        keyword
      );
      if (result.mainData) {
        ctx.body = result;
      } else {
        ctx.status = 400;
        ctx.body = result;
      }
    }
  }

  public async uploadPicture() {
    const { ctx } = this;

    const stream = await ctx.getFileStream(
      {
        limits: { fileSize: SATISFY_MAX_SIZE }
      }
    );

    const { filename } = stream;

    if (!isValidateSuffix(filename)) {
      ctx.status = 422;
      ctx.body = new Result(undefined, '文件格式不对！');
      return;
    }

    const url = await FileUtil.saveImage(stream, filename);

    ctx.body = new Result({ url }, '上传文件成功！');
  }

  public async viewPicture() {
    const { ctx } = this;

    const { filename } = ctx.query;

    const stream = FileUtil.readImage(filename);

    ctx.set('Content-type', 'image/jpeg');
    ctx.body = stream;
  }

  public async deletePicture() {
    const { ctx } = this;

    ctx.validate({
      filename: 'string',
      databaseName: { required: false, type: 'string' }
    }, ctx.request.body);

    const { filename, databaseName } = ctx.request.body;

    try {
      const fileDelete = await FileUtil.deleteImage(filename);

      let databaseDelete;
      if (databaseName) {
        databaseDelete = await ctx.service.product.deleteImage(databaseName);
        ctx.body = new Result({ fileDelete, databaseDelete }, '删除成功');
      }
    } catch (e) {
      console.log(e);
    }
  }

  public async getProductDetail() {
    const { ctx } = this;

    ctx.validate({
      productUuid: 'string',
    }, ctx.query);

    const { productUuid } = ctx.query;

    const result = await ctx.service.product.getProductDetail(productUuid);

    if (result) {
      ctx.body = new Result({ result });
      return;
    }
    ctx.status = 422;
    ctx.body = new Result({}, '获取详情信息失败');
  }
}
